#include <string.h>
#include <unordered_map>
#include <string>
#include <iomanip>
#include <sstream>
#include "job.hpp"
#include "clock.hpp"
#include "logger.hpp"
#include "kernel.hpp"
#include "FSCP_Utils.hpp"
#include "util.hpp"
#include "security_config.hpp"

// Access to the global OS instance
extern qOS::core& os;

using namespace qOS;

//==============================================================================
// JobDependency implementation
JobDependency::JobDependency()
    : fromTaskId(0)
    , toTaskId(0)
    , condition(0)
{
}

JobDependency::JobDependency(size_t from, size_t to, uint32_t cond)
    : fromTaskId(from)
    , toTaskId(to)
    , condition(cond)
{
}

//==============================================================================
// JobTimingAttr implementation
JobTimingAttr::JobTimingAttr()
    : release_time(0)
    , deadline(0)
    , period(0)
    , wcet(0)
    , jitter_bound(0)
    , slack(0)
{
}

JobTimingAttr::JobTimingAttr(uint64_t rel, uint64_t ddl, uint64_t per, 
                          uint64_t wc, uint64_t jit, uint64_t slk)
    : release_time(rel)
    , deadline(ddl)
    , period(per)
    , wcet(wc)
    , jitter_bound(jit)
    , slack(slk)
{
}

//==============================================================================
// JobStatistics implementation
JobStatistics::JobStatistics()
    : executionCount(0)
    , successCount(0)
    , failureCount(0)
    , totalExecutionTime(0)
    , lastExecutionTime(0)
    , startTime(0)
{
}

//==============================================================================
// JobConfig implementation
JobConfig::JobConfig()
    : executionMode(JobExecutionMode::SEQUENTIAL)
    , timeout(0)
    , maxRetries(0)
    , autoStart(false)
    , timingAttr()
{
    name[0] = '\0';
}
//==============================================================================
JobConfig::JobConfig(const char *jobName, JobExecutionMode mode, 
                     uint32_t to, uint32_t retries, bool start,
                     const JobTimingAttr& timing)
    : executionMode(mode)
    , timeout(to)
    , maxRetries(retries)
    , autoStart(start)
    , timingAttr(timing)
{
    if (jobName != nullptr) {
        strncpy(name, jobName, MAX_NAME_LENGTH - 1);
        name[MAX_NAME_LENGTH - 1] = '\0';
    }
    else {
        name[0] = '\0';
    }
}
//==============================================================================
// Job class implementation
Job::Job(const JobConfig &jobConfig, uint64_t securityToken)
    : config(jobConfig)
    , state(JobState::CREATED)
    , taskCount(0)
    , currentRetryCount(0)
    , nextReleaseTime(0)
    , currentExecutionStart(0)
    , periodicEnabled(false)
    , pauseTime(0)
    , pausedExecutionTime(0)
    , currentTaskIndex(0)
    , wasPeriodicBeforePause(false)
    , originalPeriod(0)
{
    // Initialize security system
    SecurityManager::initialize();
    
    // Initialize arrays
    for (size_t i = 0;  i < MAX_TASKS_PER_JOB;  i++) {
        taskArray[i] = nullptr;
        taskCompletionFlags[i] = false;
        taskErrorFlags[i] = false;
    }

    static uint32_t tokenCounter = 0;
    static uint64_t lastToken = 0;

    if (0 == securityToken) {
        // Use unified security token generation from util
        const uint64_t currentTime = clock::getTick();
        const uint64_t timeFactor = (currentTime & 0xFFFFFFFFFFFFFFFFULL) ^ (currentTime >> 32);

        m_securityToken = util::generateSecurityToken(this, timeFactor, tokenCounter, lastToken);
        lastToken = m_securityToken;
        tokenCounter++;
    }
    else {
        m_securityToken = securityToken;
    }
}
//==============================================================================
Job::~Job()
{
    cleanup(m_securityToken);
}
//==============================================================================

//==============================================================================
bool Job::addDependency(const JobDependency &dependency)
{
    return dependencyList.insert(const_cast<JobDependency*>(&dependency));
}
//==============================================================================
bool Job::submit(core &os_fscp, task tasks[], size_t count, uint64_t securityToken)
{
    // Enhanced Token Execution Check for functional safety
    if (securityToken != m_securityToken) {
        // Security violation - log critical error
        logger::out(logger::error) << "SECURITY BREACH: Invalid token attempt on Job::submit for: " << config.name 
                                 << " (expected: " << m_securityToken 
                                 << ", received: " << securityToken << ")";
        
        if (nullptr != os.mRunningErrorHandler) {
            char buf[256];
            snprintf(buf, sizeof(buf), "SECURITY BREACH: Job::submit token mismatch for job: %s", config.name);
            os.mRunningErrorHandler(FSCP_ErrorType::SECURITY_BREACH, buf, nullptr);
        }
        
        // Enhanced security reporting
        SecurityManager::reportViolation(FSCP_ErrorType::SECURITY_BREACH, "Job::submit token mismatch");
        
        if (securityToken == 0) {
            logger::out(logger::error) << "SECURITY: Null token attack detected on job: " << config.name;
            SecurityManager::reportViolation(FSCP_ErrorType::UNAUTHORIZED_ACCESS, "Null token attack");
        }
        
        return false;
    }
    
    // Validate job state integrity
    if (taskCount > MAX_TASKS_PER_JOB) {
        logger::out(logger::error) << "SECURITY: Task count corruption detected in job: " << config.name;
        return false;
    }

    // Handle initialization if tasks are provided
    if (tasks != nullptr && count > 0) {
        if (state != JobState::CREATED) {
            logger::out(logger::warning) << "Job already initialized, ignoring task parameters: " << config.name;
        } else {
            // Perform initialization logic
            if (count > MAX_TASKS_PER_JOB) {
                logger::out(logger::error) << "Too many tasks for job initialization: " << config.name;
                return false;
            }

            // Store pointers to original tasks and set up parent-child relationship
            for (size_t i = 0; i < count; i++) {
                taskArray[i] = &tasks[i];
                
                // Set this Job as the parent of the task
                if (!tasks[i].setParentJob(this, m_securityToken)) {
                    logger::out(logger::error) << "Task " << i << " already has a parent Job: " << config.name;
                    return false;
                }
                
                taskCompletionFlags[i] = false;
                taskErrorFlags[i] = false;
            }

            taskCount = count;
            state = JobState::INITIALIZED;
            logger::out(logger::info) << "Job initialized within submit: " << config.name << " with " << count << " tasks";
        }
    }

    if ((state != JobState::INITIALIZED) && (state != JobState::PAUSED)) {
        logger::out(logger::warning) << "Job not ready to submit: " << config.name;
        return false;
    }

    // Enhanced timing and safety constraints before submission
    uint64_t currentTime = clock::getTick();
    
    // Validate timing constraints for functional safety
    if (!isReady(currentTime)) {
        logger::out(logger::warning) << "Job not ready to submit (release time not reached): " << config.name;
        return false;
    }
    
    // Deadline missed detection - critical for real-time safety
    if (config.timingAttr.deadline > 0 && currentTime > config.timingAttr.deadline) {
        logger::out(logger::error) << "SECURITY: Deadline already missed for job: " << config.name
                                 << " (current: " << currentTime 
                                 << ", deadline: " << config.timingAttr.deadline << ")";
        
        if (nullptr != os.mRunningErrorHandler) {
            char buf[256];
            snprintf(buf, sizeof(buf), "Functional safety: Deadline missed for job: %s", config.name);
            os.mRunningErrorHandler(FSCP_ErrorType::DEADLINE_MISSED, buf, nullptr);
        }
        return false;
    }
    
    // WCET safety check
    if (config.timingAttr.wcet > 0 && config.timingAttr.deadline > 0) {
        if (config.timingAttr.wcet > (config.timingAttr.deadline - config.timingAttr.release_time)) {
            logger::out(logger::error) << "SECURITY: WCET exceeds available time window for job: " << config.name;
            return false;
        }
    }

    // Enhanced task submission with comprehensive safety checks
    size_t successfulSubmissions = 0;
    size_t failedSubmissions = 0;
    
    for (size_t i = 0;  i < taskCount;  i++) {
        if (taskArray[i] != nullptr) {
            // Verify task integrity before submission
            if (taskArray[i]->GetSecurityToken() == 0) {
                logger::out(logger::error) << "SECURITY: Task " << i << " has invalid token in job: " << config.name;
                failedSubmissions++;
                continue;
            }
            
            // Set timing attributes with validation
            TaskTimingAttr taskTiming;
            taskTiming.release_time = config.timingAttr.release_time;
            taskTiming.deadline = config.timingAttr.deadline;
            taskTiming.period = config.timingAttr.period;
            taskTiming.wcet = config.timingAttr.wcet;
            taskTiming.jitter_bound = config.timingAttr.jitter_bound;
            
            if (!taskArray[i]->setTimingAttributes(taskTiming)) {
                logger::out(logger::error) << "SECURITY: Failed to set timing for task " << i << " in job: " << config.name;
                failedSubmissions++;
                continue;
            }

            // Initialize task completion flags safely
            taskCompletionFlags[i] = false;
            taskErrorFlags[i] = false;

            // Submit task to scheduler with error handling
            if (!os_fscp.add(*taskArray[i], taskArray[i]->getCallback(), core::MEDIUM_PRIORITY, nullptr)) {
                logger::out(logger::error) << "SECURITY: Failed to submit task " << i << " to scheduler in job: " << config.name;
                failedSubmissions++;
            } else {
                successfulSubmissions++;
                logger::out(logger::debug) << "SECURITY: Task " << i << " successfully submitted to scheduler in job: " << config.name;
            }
        } else {
            logger::out(logger::error) << "SECURITY: Null task pointer detected at index " << i << " in job: " << config.name;
            failedSubmissions++;
        }
    }
    
    // Critical safety check - ensure at least one task was submitted successfully
    if (successfulSubmissions == 0) {
        logger::out(logger::error) << "SECURITY CRITICAL: No tasks could be submitted for job: " << config.name;
        if (nullptr != os.mRunningErrorHandler) {
            char buf[256];
            snprintf(buf, sizeof(buf), "Functional safety: No tasks submitted for job: %s", config.name);
            os.mRunningErrorHandler(FSCP_ErrorType::CRITICAL_ERROR, buf, nullptr);
        }
        return false;
    }
    
    // Log submission statistics for security audit
    logger::out(logger::info) << "SECURITY: Job submission completed - Success: " << successfulSubmissions 
                               << ", Failed: " << failedSubmissions << " for job: " << config.name;

    // Final state transition with safety validation
    if (taskCount == 0 || taskCount > MAX_TASKS_PER_JOB) {
        logger::out(logger::error) << "SECURITY: Invalid task count during state transition in job: " << config.name;
        return false;
    }
    
    state = JobState::RUNNING;
    stats.startTime = currentTime;
    currentExecutionStart = currentTime;

    // Security audit for successful job submission
    logger::out(logger::info) << "Job submitted: " << config.name << " with " << taskCount << " tasks in "
                             << (config.executionMode == JobExecutionMode::SEQUENTIAL ? "sequential" :
                                 config.executionMode == JobExecutionMode::PARALLEL ? "parallel" : "other")
                             << " mode";
                             
    logger::out(logger::info) << "SECURITY: Job successfully submitted to scheduler: " << config.name
                               << " (tasks: " << taskCount << ", start time: " << currentTime << ")";
    
    // Post-submission safety check
    if (stats.startTime == 0 || currentExecutionStart == 0) {
        logger::out(logger::error) << "SECURITY: Timing initialization failed in job: " << config.name;
    }
    
    return true;
}
//==============================================================================
void Job::pause(uint64_t securityToken)
{
    // Token Execution Check for functional safety
    if (securityToken != m_securityToken) {
        if (nullptr != os.mRunningErrorHandler) {
            char buf[256];
            snprintf(buf, sizeof(buf), "Job::pause: Security token mismatch for job: %s", config.name);
            os.mRunningErrorHandler(FSCP_ErrorType::MEMORY_ERROR, buf, nullptr);
        }
        return;
    }

    if (canPause()) {
        savePauseState();
        state = JobState::PAUSED;
        logger::out(logger::info) << "Job paused: " << config.name
                                 << " at task " << currentTaskIndex;
    }
    else {
        logger::out(logger::warning) << "Cannot pause job: " << config.name
                                     << " (state: " << static_cast<int>(state) << ")";
    }
}
//==============================================================================
void Job::resume(uint64_t securityToken)
{
    // Token Execution Check for functional safety
    if (securityToken != m_securityToken) {
        if (nullptr != os.mRunningErrorHandler) {
            char buf[256];
            snprintf(buf, sizeof(buf), "Job::resume: Security token mismatch for job: %s", config.name);
            os.mRunningErrorHandler(FSCP_ErrorType::MEMORY_ERROR, buf, nullptr);
        }
        return;
    }

    if (canResume()) {
        restoreResumeState();
        state = JobState::RUNNING;
        logger::out(logger::info) << "Job resumed: " << config.name
                                 << " after " << getPauseDuration() << " microseconds";
    }
    else {
        logger::out(logger::warning) << "Cannot resume job: " << config.name
                                     << " (state: " << static_cast<int>(state) << ")";
    }
}
//==============================================================================
bool Job::forcePause(uint64_t securityToken)
{
    // Token Execution Check for functional safety
    if (securityToken != m_securityToken) {
        if (nullptr != os.mRunningErrorHandler) {
            char buf[256];
            snprintf(buf, sizeof(buf), "Job::forcePause: Security token mismatch for job: %s", config.name);
            os.mRunningErrorHandler(FSCP_ErrorType::MEMORY_ERROR, buf, nullptr);
        }
        return false;
    }

    if (state == JobState::PAUSED) {
        return true; // Already paused
    }

    if ((state == JobState::CREATED) || (state == JobState::INITIALIZED)) {
        logger::out(logger::warning) << "Cannot force pause uninitialized job: " << config.name;
        return false;
    }

    if ((state == JobState::COMPLETED) || (state == JobState::ERROR)) {
        logger::out(logger::warning) << "Cannot force pause completed/failed job: " << config.name;
        return false;
    }

    savePauseState();
    state = JobState::PAUSED;
    logger::out(logger::info) << "Job force paused: " << config.name;
    return true;
}
//==============================================================================
bool Job::isPaused() const
{
    return state == JobState::PAUSED;
}
//==============================================================================
uint64_t Job::getPauseDuration() const
{
    if ((state != JobState::PAUSED) || (pauseTime == 0)) {
        return 0;
    }

    return clock::getTick() - pauseTime;
}
//==============================================================================
JobState Job::getState() const
{
    return state;
}
//==============================================================================
JobStatistics Job::getStatistics() const
{
    return stats;
}
//==============================================================================
size_t Job::getTaskCount() const
{
    return taskCount;
}
//==============================================================================
JobTimingAttr Job::getTimingAttributes() const
{
    return config.timingAttr;
}
//==============================================================================
bool Job::setTimingAttributes(const JobTimingAttr& timing)
{
    if ((state != JobState::CREATED) && (state != JobState::INITIALIZED)) {
        logger::out(logger::warning) << "Cannot set timing attributes while job is running: " << config.name;
        return false;
    }
    config.timingAttr = timing;
    return true;
}
//==============================================================================
bool Job::isPeriodic() const
{
    return config.timingAttr.period > 0;
}

uint64_t Job::getRemainingSlack(uint64_t currentTime) const
{
    if (config.timingAttr.deadline > 0) {
        return config.timingAttr.deadline - currentTime;
    }
    return 0;
}
//==============================================================================
void Job::cleanup(uint64_t securityToken)
{
    // Token Execution Check for functional safety
    if (securityToken != m_securityToken) {
        if (nullptr != os.mRunningErrorHandler) {
            char buf[256];
            snprintf(buf, sizeof(buf), "Job::cleanup: Security token mismatch for job: %s", config.name);
            os.mRunningErrorHandler(FSCP_ErrorType::MEMORY_ERROR, buf, nullptr);
        }
        return;
    }

    // Remove parent relationship from all tasks
    for (size_t i = 0;  i < taskCount;  i++) {
        if (taskArray[i] != nullptr) {
            taskArray[i]->setParentJob(nullptr, 0ULL);  // Clear parent relationship (no token needed for nullptr)
        }
    }
    
    // Reset arrays (no need to delete since they are static arrays)
    for (size_t i = 0;  i < MAX_TASKS_PER_JOB;  i++) {
        taskArray[i] = nullptr;
        taskCompletionFlags[i] = false;
        taskErrorFlags[i] = false;
    }
    
    taskCount = 0;
    state = JobState::CREATED;
}
//==============================================================================
bool Job::checkDependencies(size_t taskIndex)
{
    // Simplified implementation: check if all preceding Tasks are completed
    for (size_t i = 0;  i < taskIndex;  i++) {
        if (!taskCompletionFlags[i] && !taskErrorFlags[i]) {
            return false;
        }
    }
    return true;
}
//==============================================================================
bool Job::shouldExecuteTask(task* taskPtr, uint64_t securityToken)
{
    // Token Execution Check for functional safety
    if (taskPtr != nullptr && securityToken != taskPtr->GetSecurityToken()) {
        if (nullptr != os.mRunningErrorHandler) {
            char buf[256];
            snprintf(buf, sizeof(buf), "Job::shouldExecuteTask: Security token mismatch for task: %s", taskPtr->getName());
            os.mRunningErrorHandler(FSCP_ErrorType::MEMORY_ERROR, buf, nullptr);
        }
        return false;
    }

    if (config.executionMode != JobExecutionMode::SEQUENTIAL) {
        return true;  // Non-sequential modes allow all tasks to execute
    }

    // For sequential mode, find the task index and check if it's the next to execute
    for (size_t i = 0;  i < taskCount;  i++) {
        if (taskArray[i] == taskPtr) {
            // Check if all previous tasks are completed
            for (size_t j = 0;  j < i;  j++) {
                if (!taskCompletionFlags[j] && !taskErrorFlags[j]) {
                    return false;  // Previous task not completed yet
                }
            }
            return true;  // This task's turn
        }
    }

    return false;  // Task not found in this job
}
//==============================================================================
JobExecutionMode Job::getExecutionMode() const
{
    return config.executionMode;
}
//==============================================================================
bool Job::isJobCompleted()
{
    for (size_t i = 0;  i < taskCount;  i++) {
        if (!taskCompletionFlags[i] && !taskErrorFlags[i]) {
            return false;
        }
    }

    return true;
}
//==============================================================================
bool Job::isJobFailed()
{
    for (size_t i = 0;  i < taskCount;  i++) {
        if (taskErrorFlags[i]) {
            return true;
        }
    }

    return false;
}
//==============================================================================
bool Job::checkTimingConstraints()
{
    uint64_t currentTime = clock::getTick();
    
    // Check if job is ready to execute (release time)
    if (!isReady(currentTime)) {
        return false;
    }
    
    // Check if deadline is missed
    if (isDeadlineMissed(currentTime)) {
        logger::out(logger::error) << "Job deadline missed: " << config.name;
        if (nullptr != os.mRunningErrorHandler) {
            char buf[256];
            snprintf(buf, sizeof(buf), "Job deadline missed: %s", config.name);
            os.mRunningErrorHandler(FSCP_ErrorType::MEMORY_ERROR, buf, nullptr);
        }
        completeJob(false);
        return false;
    }
    
    // Check job timeout (if configured)
    if (config.timeout > 0) {
        uint64_t elapsedTime = currentTime - stats.startTime;
        if (elapsedTime > (config.timeout * 1000ULL)) {  // Convert ms to microseconds
            logger::out(logger::error) << "Job timeout: " << config.name
                                     << " after " << elapsedTime << " microseconds";
            if (nullptr != os.mRunningErrorHandler) {
                char buf[256];
                snprintf(buf, sizeof(buf), "Job timeout: %s", config.name);
                os.mRunningErrorHandler(FSCP_ErrorType::MEMORY_ERROR, buf, nullptr);
            }
            completeJob(false);
            return false;
        }
    }

    // Check WCET violation (if job has been running)
    if ((config.timingAttr.wcet > 0) && (currentExecutionStart > 0)) {
        uint64_t executionTime = currentTime - currentExecutionStart;
        if (executionTime > config.timingAttr.wcet) {
            logger::out(logger::warning) << "Job WCET violation: " << config.name
                                        << " execution time " << executionTime
                                        << " > WCET " << config.timingAttr.wcet;
            // WCET violation is a warning, not necessarily a failure
        }
    }

    // Check jitter bound (for periodic jobs)
    if ((config.timingAttr.jitter_bound > 0) && periodicEnabled &&
                                                        (nextReleaseTime > 0)) {
        uint64_t expectedRelease = currentExecutionStart + config.timingAttr.period;
        int64_t jitter = static_cast<int64_t>(nextReleaseTime) -
                                            static_cast<int64_t>(expectedRelease);
        if (jitter < 0) {
            jitter = -jitter;  // Absolute value
        }

        if (static_cast<uint64_t>(jitter) > config.timingAttr.jitter_bound) {
            logger::out(logger::warning) << "Job jitter bound exceeded: " << config.name
                                        << " jitter " << jitter
                                        << " > bound " << config.timingAttr.jitter_bound;
        }
    }

    // Update slack time
    updateSlack(currentTime);
    
    return true;
}
//==============================================================================
void Job::completeJob(bool success)
{
    uint64_t currentTime = clock::getTick();
    stats.lastExecutionTime = currentTime - stats.startTime;
    stats.totalExecutionTime += stats.lastExecutionTime;
    stats.executionCount++;
    
    if (success) {
        stats.successCount++;
        state = JobState::COMPLETED;
        logger::out(logger::info) << "Job completed successfully: " << config.name;
        
        // Handle periodic execution
        if (periodicEnabled) {
            // Schedule next execution
            nextReleaseTime = currentTime + config.timingAttr.period;
            state = JobState::INITIALIZED;
            logger::out(logger::debug) << "Job scheduled for next execution at: " << nextReleaseTime;
        }
    }
    else {
        stats.failureCount++;
        state = JobState::ERROR;
        logger::out(logger::error) << "Job failed: " << config.name;
        
        // Handle retry logic
        if (currentRetryCount < config.maxRetries) {
            currentRetryCount++;
            logger::out(logger::warning) << "Retrying job " << config.name 
                                         << " (attempt " << currentRetryCount << " of " 
                                         << config.maxRetries << ")";
            resetJob();
        }
    }
}
//==============================================================================
void Job::resetJob()
{
    for (size_t i = 0;  i < taskCount;  i++) {
        taskCompletionFlags[i] = false;
        taskErrorFlags[i] = false;
    }
    state = JobState::RUNNING;
    currentExecutionStart = clock::getTick();
    stats.startTime = currentExecutionStart;
}
//==============================================================================
bool Job::isReady(uint64_t currentTime) const
{
    if (config.timingAttr.release_time > 0) {
        return currentTime >= config.timingAttr.release_time;
    }

    return true;
}
//==============================================================================
bool Job::isDeadlineMissed(uint64_t currentTime) const
{
    if (config.timingAttr.deadline > 0) {
        return currentTime > config.timingAttr.deadline;
    }

    return false;
}
//==============================================================================
uint64_t Job::updateSlack(uint64_t currentTime) {
    if (config.timingAttr.deadline > 0) {
        config.timingAttr.slack = config.timingAttr.deadline - currentTime;
        return config.timingAttr.slack;
    }

    return 0;
}
//==============================================================================
// Pause/Resume helper methods
void Job::savePauseState()
{
    pauseTime = clock::getTick();
    pausedExecutionTime = currentExecutionStart > 0 ?
                          pauseTime - currentExecutionStart : 0;

    // Find current task index
    currentTaskIndex = 0;
    for (size_t i = 0; i < taskCount; i++) {
        if (!taskCompletionFlags[i] && !taskErrorFlags[i]) {
            currentTaskIndex = i;
            break;
        }
        currentTaskIndex = i + 1;
    }

    // Save periodic state
    wasPeriodicBeforePause = periodicEnabled;
    originalPeriod = config.timingAttr.period;

    logger::out(logger::debug) << "Job pause state saved: " << config.name
                               << " task_index=" << currentTaskIndex
                               << " exec_time=" << pausedExecutionTime;
}
//==============================================================================
void Job::restoreResumeState()
{
    uint64_t resumeTime = clock::getTick();
    uint64_t pauseDuration = resumeTime - pauseTime;

    // Adjust execution start time to account for pause duration
    if (currentExecutionStart > 0) {
        currentExecutionStart += pauseDuration;
    }

    // Adjust timing attributes for periodic jobs
    if (wasPeriodicBeforePause && originalPeriod > 0) {
        // Adjust next release time to account for pause
        if (nextReleaseTime > 0) {
            nextReleaseTime += pauseDuration;
        }

        // Recalculate deadline if it was set
        if (config.timingAttr.deadline > 0) {
            config.timingAttr.deadline += pauseDuration;
        }
    }

    // Reset pause state
    pauseTime = 0;
    pausedExecutionTime = 0;

    logger::out(logger::debug) << "Job resume state restored: " << config.name
                               << " pause_duration=" << pauseDuration
                               << " new_exec_start=" << currentExecutionStart;
}
//==============================================================================
bool Job::canPause() const
{
    return state == JobState::RUNNING;
}
//==============================================================================
bool Job::canResume() const
{
    return state == JobState::PAUSED;
}
//==============================================================================
void Job::notifyTaskStarted(size_t taskIndex, uint64_t securityToken)
{
    // Token Execution Check for functional safety
    if (securityToken != m_securityToken) {
        if (nullptr != os.mRunningErrorHandler) {
            char buf[256];
            snprintf(buf, sizeof(buf), "Job::notifyTaskStarted: Security token mismatch for job: %s", config.name);
            os.mRunningErrorHandler(FSCP_ErrorType::MEMORY_ERROR, buf, nullptr);
        }
        return;
    }

    if (taskIndex < taskCount) {
        taskCompletionFlags[taskIndex] = false;
        taskErrorFlags[taskIndex] = false;
        logger::out(logger::debug) << "Task " << taskIndex << " started in job: " << config.name;
    }
}
//==============================================================================
void Job::notifyTaskCompleted(size_t taskIndex, bool success, uint64_t securityToken)
{
    // Token Execution Check for functional safety
    if (securityToken != m_securityToken) {
        if (nullptr != os.mRunningErrorHandler) {
            char buf[256];
            snprintf(buf, sizeof(buf), "Job::notifyTaskCompleted: Security token mismatch for job: %s", config.name);
            os.mRunningErrorHandler(FSCP_ErrorType::MEMORY_ERROR, buf, nullptr);
        }
        return;
    }

    if (taskIndex < taskCount) {
        taskCompletionFlags[taskIndex] = true;
        taskErrorFlags[taskIndex] = !success;
        
        if (success) {
            logger::out(logger::debug) << "Task " << taskIndex << " completed successfully in job: " << config.name;
        }
        else {
            logger::out(logger::warning) << "Task " << taskIndex << " completed with errors in job: " << config.name;
        }
        
        // Update job statistics
        stats.executionCount++;
        if (success) {
            stats.successCount++;
        }
        else {
            stats.failureCount++;
        }
        
        // Check if job is complete based on execution mode
        if (config.executionMode == JobExecutionMode::SEQUENTIAL) {
            // In sequential mode, check if all tasks up to current index are complete
            bool allCompleted = true;
            for (size_t i = 0; i <= taskIndex; i++) {
                if (!taskCompletionFlags[i]) {
                    allCompleted = false;
                    break;
                }
            }
            if (allCompleted && taskIndex == taskCount - 1) {
                state = JobState::COMPLETED;
                logger::out(logger::info) << "Job completed (sequential): " << config.name;
            }
        }
        else if (config.executionMode == JobExecutionMode::PARALLEL) {
            // In parallel mode, check if all tasks are complete
            if (areAllTasksCompleted()) {
                state = JobState::COMPLETED;
                logger::out(logger::info) << "Job completed (parallel): " << config.name;
            }
        }
    }
}
//==============================================================================
void Job::notifyTaskError(size_t taskIndex, uint32_t errorCode, uint64_t securityToken)
{
    // Token Execution Check for functional safety
    if (securityToken != m_securityToken) {
        if (nullptr != os.mRunningErrorHandler) {
            char buf[256];
            snprintf(buf, sizeof(buf), "Job::notifyTaskError: Security token mismatch for job: %s", config.name);
            os.mRunningErrorHandler(FSCP_ErrorType::MEMORY_ERROR, buf, nullptr);
        }
        return;
    }

    if (taskIndex < taskCount) {
        taskErrorFlags[taskIndex] = true;
        logger::out(logger::error) << "Task " << taskIndex << " error in job: " << config.name << " (code: " << errorCode << ")";
        
        // Update job statistics
        stats.failureCount++;
        
        // Check if job should fail based on error handling policy
        // For now, any task error marks the job as failed
        state = JobState::ERROR;
        logger::out(logger::error) << "Job failed due to task error: " << config.name;
    }
}
//==============================================================================
task* Job::getTask(size_t taskIndex, uint64_t securityToken) const
{
    // Token Execution Check for functional safety
    if (taskIndex < taskCount && taskArray[taskIndex] != nullptr) {
        if (securityToken != taskArray[taskIndex]->GetSecurityToken()) {
            if (nullptr != os.mRunningErrorHandler) {
                char buf[256];
                snprintf(buf, sizeof(buf), "Job::getTask: Security token mismatch for task index: %zu", taskIndex);
                os.mRunningErrorHandler(FSCP_ErrorType::MEMORY_ERROR, buf, nullptr);
            }
            return nullptr;
        }
        return taskArray[taskIndex];
    }
    return nullptr;
}
//==============================================================================
size_t Job::findTaskIndex(const task* taskPtr, uint64_t securityToken) const
{
    // Token Execution Check for functional safety
    if (taskPtr != nullptr && securityToken != taskPtr->GetSecurityToken()) {
        if (nullptr != os.mRunningErrorHandler) {
            char buf[256];
            snprintf(buf, sizeof(buf), "Job::findTaskIndex: Security token mismatch for task: %s", taskPtr->getName());
            os.mRunningErrorHandler(FSCP_ErrorType::MEMORY_ERROR, buf, nullptr);
        }
        return SIZE_MAX;
    }

    for (size_t i = 0; i < taskCount; i++) {
        if (taskArray[i] == taskPtr) {
            return i;
        }
    }
    return SIZE_MAX;
}
//==============================================================================
bool Job::areAllTasksCompleted() const
{
    for (size_t i = 0; i < taskCount; i++) {
        if (!taskCompletionFlags[i]) {
            return false;
        }
    }
    return true;
}
//==============================================================================
bool Job::hasAnyTaskFailed() const
{
    for (size_t i = 0; i < taskCount; i++) {
        if (taskErrorFlags[i]) {
            return true;
        }
    }
    return false;
}

//==============================================================================
const char* Job::getName() const
{
    return config.name;
}
